package com.student.grade.service.impl;

import com.student.common.entity.Grade;
import com.student.common.entity.Course;
import com.student.grade.service.GradeService;
import com.student.grade.repository.GradeRepository;
import com.student.grade.dto.GradeDTO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import org.springframework.web.client.RestTemplate;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 成绩服务实现类
 * 
 * @author student
 * @date 2025
 */
@Service
public class GradeServiceImpl implements GradeService {
    
    @Autowired
    private GradeRepository gradeRepository;
    
    @Autowired
    private RestTemplate restTemplate;
    
    /**
     * 验证用户是否有权限录入该课程的成绩
     */
    private boolean validateTeacherPermission(String teacherId, String courseId) {
        try {
            // 调用课程服务获取课程信息
            String url = "http://course-service/course/" + courseId;
            Course course = restTemplate.getForObject(url, Course.class);
            
            if (course != null) {
                // 如果是课程的授课教师，有权限录入
                if (teacherId.equals(course.getTeacherId())) {
                    return true;
                }
                
                // 检查是否为管理员角色
                if (isAdminUser(teacherId)) {
                    return true;
                }
            }
            return false;
        } catch (Exception e) {
            // 如果调用课程服务失败，为了不影响系统运行，暂时允许录入
            // 在实际生产环境中，应该记录日志并返回false
            System.err.println("验证教师权限失败: " + e.getMessage());
            return true;
        }
    }
    
    /**
     * 检查是否为管理员用户
     */
    private boolean isAdminUser(String teacherId) {
        try {
            // 调用用户服务获取用户信息
            String url = "http://user-service/user/related/" + teacherId;
            // 这里简化处理，直接检查teacherId是否为T001（管理员）
            // 实际应该调用用户服务获取用户角色信息
            return "T001".equals(teacherId);
        } catch (Exception e) {
            System.err.println("检查管理员权限失败: " + e.getMessage());
            return false;
        }
    }
    
    @Override
    public boolean inputGrade(Grade grade) {
        // 验证教师权限
        if (!validateTeacherPermission(grade.getTeacherId(), grade.getCourseId())) {
            return false;
        }
        
        // 检查是否已存在该成绩记录
        if (gradeRepository.existsByStudentIdAndCourseIdAndSemester(
                grade.getStudentId(), grade.getCourseId(), grade.getSemester())) {
            return false;
        }
        
        // 验证成绩范围
        if (grade.getScore().compareTo(BigDecimal.ZERO) < 0 || 
            grade.getScore().compareTo(new BigDecimal("100")) > 0) {
            return false;
        }
        
        grade.setInputTime(LocalDateTime.now());
        grade.setCreateTime(LocalDateTime.now());
        grade.setUpdateTime(LocalDateTime.now());
        
        gradeRepository.save(grade);
        return true;
    }
    
    @Override
    public boolean updateGrade(Grade grade) {
        if (!gradeRepository.existsById(grade.getGradeId())) {
            return false;
        }
        
        // 获取原有成绩记录，确保不丢失必要数据
        Grade existingGrade = gradeRepository.findById(grade.getGradeId()).orElse(null);
        if (existingGrade == null) {
            return false;
        }
        
        // 验证教师权限
        if (!validateTeacherPermission(grade.getTeacherId(), grade.getCourseId())) {
            return false;
        }
        
        // 验证成绩范围
        if (grade.getScore().compareTo(BigDecimal.ZERO) < 0 || 
            grade.getScore().compareTo(new BigDecimal("100")) > 0) {
            return false;
        }
        
        // 保留原有的必要数据，只更新允许修改的字段
        existingGrade.setScore(grade.getScore());
        existingGrade.setGradeType(grade.getGradeType());
        existingGrade.setSemester(grade.getSemester());
        existingGrade.setUpdateTime(LocalDateTime.now());
        
        gradeRepository.save(existingGrade);
        return true;
    }
    
    @Override
    public Page<Grade> getStudentGrades(String studentId, String semester, Pageable pageable) {
        if (StringUtils.hasText(semester)) {
            return gradeRepository.findByStudentIdAndSemester(studentId, semester, pageable);
        }
        return gradeRepository.findByStudentId(studentId, pageable);
    }
    
    @Override
    public Page<Grade> getCourseGrades(String courseId, String semester, Pageable pageable) {
        if (StringUtils.hasText(semester)) {
            return gradeRepository.findByCourseIdAndSemester(courseId, semester, pageable);
        }
        return gradeRepository.findByCourseId(courseId, pageable);
    }
    
    @Override
    public Object getGradeStatistics(String semester) {
        Map<String, Object> statistics = new HashMap<>();
        
        if (StringUtils.hasText(semester)) {
            long totalGrades = gradeRepository.countBySemester(semester);
            statistics.put("totalGrades", totalGrades);
            statistics.put("semester", semester);
        } else {
            long totalGrades = gradeRepository.count();
            statistics.put("totalGrades", totalGrades);
        }
        
        return statistics;
    }
    
    @Override
    public Page<Grade> getGradeList(Pageable pageable, String studentId, String courseId, String semester, String gradeType) {
        if (StringUtils.hasText(studentId) || StringUtils.hasText(courseId) || 
            StringUtils.hasText(semester) || StringUtils.hasText(gradeType)) {
            return gradeRepository.findByConditions(studentId, courseId, semester, gradeType, pageable);
        }
        return gradeRepository.findAll(pageable);
    }
    
    @Override
    public Page<GradeDTO> getGradeListWithDetails(Pageable pageable, String studentId, String courseId, String semester, String gradeType) {
        List<Object[]> rawResults;
        long totalCount;
        
        if (StringUtils.hasText(studentId) || StringUtils.hasText(courseId) || 
            StringUtils.hasText(semester) || StringUtils.hasText(gradeType)) {
            rawResults = gradeRepository.findByConditionsWithDetailsRaw(studentId, courseId, semester, gradeType, pageable);
            totalCount = gradeRepository.countByConditions(studentId, courseId, semester, gradeType);
        } else {
            rawResults = gradeRepository.findByConditionsWithDetailsRaw(null, null, null, null, pageable);
            totalCount = gradeRepository.count();
        }
        
        // 转换原始结果为GradeDTO
        List<GradeDTO> gradeDTOs = convertToGradeDTO(rawResults);
        
        return new org.springframework.data.domain.PageImpl<>(gradeDTOs, pageable, totalCount);
    }
    
    /**
     * 将原始查询结果转换为GradeDTO列表
     */
    private List<GradeDTO> convertToGradeDTO(List<Object[]> rawResults) {
        List<GradeDTO> gradeDTOs = new ArrayList<>();
        
        for (Object[] row : rawResults) {
            GradeDTO dto = new GradeDTO();
            dto.setGradeId(row[0] != null ? ((Number) row[0]).longValue() : null);
            dto.setStudentId(row[1] != null ? row[1].toString() : null);
            dto.setStudentName(row[2] != null ? row[2].toString() : null);
            dto.setCourseId(row[3] != null ? row[3].toString() : null);
            dto.setCourseCode(row[4] != null ? row[4].toString() : null);
            dto.setCourseName(row[5] != null ? row[5].toString() : null);
            dto.setTeacherId(row[6] != null ? row[6].toString() : null);
            dto.setScore(row[7] != null ? (BigDecimal) row[7] : null);
            dto.setGradeType(row[8] != null ? row[8].toString() : null);
            dto.setSemester(row[9] != null ? row[9].toString() : null);
            dto.setInputTime(row[10] != null ? convertToLocalDateTime(row[10]) : null);
            dto.setCreateTime(row[11] != null ? convertToLocalDateTime(row[11]) : null);
            dto.setUpdateTime(row[12] != null ? convertToLocalDateTime(row[12]) : null);
            
            gradeDTOs.add(dto);
        }
        
        return gradeDTOs;
    }
    
    /**
     * 将时间对象转换为LocalDateTime
     */
    private LocalDateTime convertToLocalDateTime(Object timeObj) {
        if (timeObj == null) {
            return null;
        }
        
        if (timeObj instanceof LocalDateTime) {
            return (LocalDateTime) timeObj;
        } else if (timeObj instanceof java.sql.Timestamp) {
            return ((java.sql.Timestamp) timeObj).toLocalDateTime();
        } else if (timeObj instanceof java.sql.Date) {
            return ((java.sql.Date) timeObj).toLocalDate().atStartOfDay();
        } else if (timeObj instanceof java.util.Date) {
            return ((java.util.Date) timeObj).toInstant()
                    .atZone(java.time.ZoneId.systemDefault())
                    .toLocalDateTime();
        }
        
        return null;
    }
    
    @Override
    public Grade getGradeById(Long gradeId) {
        return gradeRepository.findById(gradeId).orElse(null);
    }
}
